<template>
  <view class="snake-game">
    <view class="game-container">
      <canvas 
        class="game-canvas" 
        canvas-id="snakeCanvas"
        :style="{ width: canvasSize + 'px', height: canvasSize + 'px' }"
        @touchstart="handleTouchStart"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
        @mousedown="handleMouseDown"
        @mousemove="handleMouseMove"
        @mouseup="handleMouseUp">
      </canvas>
      
      <!-- web端键盘控制提示 -->
      <!-- #ifdef H5 -->
      <view class="keyboard-tips">
        <text>使用键盘 ↑←↓→ 方向键控制</text>
      </view>
      <!-- #endif -->
    </view>

    <view class="control-panel">
      <view class="game-info">
        <view class="score">得分: {{score}}</view>
        <view class="high-score">最高分: {{highScore}}</view>
      </view>
      
      <view class="buttons">
        <button class="control-btn" @tap="toggleGame">
          {{isPlaying ? '暂停' : '开始'}}
        </button>
        <button class="control-btn" @tap="restartGame">
          重新开始
        </button>
      </view>
      
      <!-- 移动端虚拟方向键 -->
      <!-- #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO -->
      <view class="direction-keys">
        <view class="key-row">
          <button class="key-btn" @tap="changeDirection('up')">↑</button>
        </view>
        <view class="key-row">
          <button class="key-btn" @tap="changeDirection('left')">←</button>
          <button class="key-btn" @tap="changeDirection('down')">↓</button>
          <button class="key-btn" @tap="changeDirection('right')">→</button>
        </view>
      </view>
      <!-- #endif -->
    </view>

    <!-- 添加排行榜 -->
    <view class="rank-section">
      <rank-list :rankings="rankList" />
    </view>
  </view>
</template>

<script>
import RankList from '../../components/rank-list/index.vue'

const STORAGE_KEY = 'snake_high_score'
const RANK_STORAGE_KEY = 'snake_rank_list'
const MAX_RANK_COUNT = 50 // 最多保存50条记录

export default {
  components: {
    RankList
  },
  
  data() {
    return {
      ctx: null,
      snake: [],
      food: {x: 0, y: 0},
      direction: 'right',
      nextDirection: 'right', // 防止快速按键导致的自杀
      gridSize: 20,
      speed: 200,
      timer: null,
      isPlaying: false,
      score: 0,
      highScore: 0,
      touchStartX: 0,
      touchStartY: 0,
      canvasSize: 300,
      isMouseDown: false,
      mouseStartX: 0,
      mouseStartY: 0,
      rankList: [],
      currentUser: {
        nickname: '',
        avatar: ''
      }
    }
  },
  
  onLoad() {
    // 读取历史最高分
    try {
      const highScore = uni.getStorageSync(STORAGE_KEY)
      if(highScore) {
        this.highScore = parseInt(highScore)
      }
    } catch(e) {
      console.error('读取最高分失败:', e)
    }
    
    // 设置画布大小
    const systemInfo = uni.getSystemInfoSync()
    const minSize = Math.min(systemInfo.windowWidth * 0.9, systemInfo.windowHeight * 0.6)
    this.canvasSize = Math.floor(minSize / this.gridSize) * this.gridSize
    
    // 加载排行榜数据
    this.loadRankList()
    
    // 获取用户信息
    // #ifdef MP-WEIXIN
    this.getUserInfo()
    // #endif
  },
  
  onReady() {
    this.ctx = uni.createCanvasContext('snakeCanvas', this)
    this.initGame()
    
    // Web端键盘控制
    // #ifdef H5
    window.addEventListener('keydown', this.handleKeyDown)
    // #endif
  },
  
  onUnload() {
    // #ifdef H5
    window.removeEventListener('keydown', this.handleKeyDown)
    // #endif
    clearInterval(this.timer)
  },
  
  methods: {
    initGame() {
      const centerX = Math.floor((this.canvasSize / this.gridSize) / 2)
      const centerY = Math.floor((this.canvasSize / this.gridSize) / 2)
      
      this.snake = [
        {x: centerX, y: centerY},
        {x: centerX - 1, y: centerY},
        {x: centerX - 2, y: centerY}
      ]
      
      this.direction = 'right'
      this.nextDirection = 'right'
      this.generateFood()
      this.score = 0
      this.draw()
    },
    
    restartGame() {
      clearInterval(this.timer)
      this.isPlaying = false
      this.initGame()
    },
    
    generateFood() {
      const maxX = Math.floor(this.canvasSize / this.gridSize)
      const maxY = Math.floor(this.canvasSize / this.gridSize)
      
      let x, y
      do {
        x = Math.floor(Math.random() * maxX)
        y = Math.floor(Math.random() * maxY)
      } while(this.isPositionOccupied(x, y))
      
      this.food = {x, y}
    },
    
    draw() {
      const ctx = this.ctx
      const gridSize = this.gridSize
      
      // 清空画布
      ctx.clearRect(0, 0, this.canvasSize, this.canvasSize)
      
      // 绘制网格背景
      ctx.setStrokeStyle('#f0f0f0')
      for(let i = 0; i <= this.canvasSize; i += gridSize) {
        ctx.beginPath()
        ctx.moveTo(i, 0)
        ctx.lineTo(i, this.canvasSize)
        ctx.stroke()
        ctx.beginPath()
        ctx.moveTo(0, i)
        ctx.lineTo(this.canvasSize, i)
        ctx.stroke()
      }
      
      // 绘制蛇身
      this.snake.forEach((segment, index) => {
        ctx.setFillStyle(index === 0 ? '#2ecc71' : '#27ae60')
        ctx.fillRect(
          segment.x * gridSize + 1,
          segment.y * gridSize + 1,
          gridSize - 2,
          gridSize - 2
        )
      })
      
      // 绘制食物
      ctx.setFillStyle('#e74c3c')
      ctx.beginPath()
      ctx.arc(
        this.food.x * gridSize + gridSize/2,
        this.food.y * gridSize + gridSize/2,
        gridSize/2 - 2,
        0,
        2 * Math.PI
      )
      ctx.fill()
      
      ctx.draw()
    },
    
    changeDirection(newDirection) {
      const opposites = {
        up: 'down',
        down: 'up',
        left: 'right',
        right: 'left'
      }
      
      if(newDirection !== opposites[this.direction]) {
        this.nextDirection = newDirection
      }
    },
    
    move() {
      // 更新方向
      this.direction = this.nextDirection
      
      const head = {...this.snake[0]}
      
      switch(this.direction) {
        case 'up': head.y--; break
        case 'down': head.y++; break
        case 'left': head.x--; break
        case 'right': head.x++; break
      }
      
      if(head.x === this.food.x && head.y === this.food.y) {
        this.score += 10
        if(this.score > this.highScore) {
          this.highScore = this.score
          // 保存最高分
          uni.setStorage({
            key: STORAGE_KEY,
            data: this.highScore.toString()
          })
        }
        this.generateFood()
        // 加快游戏速度
        if(this.speed > 50) {
          clearInterval(this.timer)
          this.speed -= 5
          this.timer = setInterval(() => {
            this.move()
          }, this.speed)
        }
      } else {
        this.snake.pop()
      }
      
      if(this.checkCollision(head)) {
        this.gameOver()
        return
      }
      
      this.snake.unshift(head)
      this.draw()
    },
    
    handleKeyDown(e) {
      switch(e.key) {
        case 'ArrowUp': this.changeDirection('up'); break
        case 'ArrowDown': this.changeDirection('down'); break
        case 'ArrowLeft': this.changeDirection('left'); break
        case 'ArrowRight': this.changeDirection('right'); break
        case ' ': this.toggleGame(); break // 空格控制开始/暂停
      }
    },
    
    checkCollision(head) {
      const maxX = Math.floor(this.canvasSize / this.gridSize)
      const maxY = Math.floor(this.canvasSize / this.gridSize)
      
      // 检查是否撞墙
      if(head.x < 0 || head.x >= maxX || head.y < 0 || head.y >= maxY) {
        return true
      }
      
      // 检查是否撞到自己
      return this.isPositionOccupied(head.x, head.y)
    },
    
    gameOver() {
      this.isPlaying = false
      clearInterval(this.timer)
      
      // 更新排行榜
      this.updateRankList(this.score)
      
      uni.showModal({
        title: '游戏结束',
        content: `您的得分是: ${this.score}`,
        showCancel: false,
        success: () => {
          this.initGame()
        }
      })
    },
    
    toggleGame() {
      if(this.isPlaying) {
        clearInterval(this.timer)
      } else {
        this.timer = setInterval(() => {
          this.move()
        }, this.speed)
      }
      this.isPlaying = !this.isPlaying
    },
    
    isPositionOccupied(x, y) {
      // 检查位置是否被蛇身占据
      return this.snake.some(segment => segment.x === x && segment.y === y)
    },
    
    getCanvasWidth() {
      return uni.getSystemInfoSync().windowWidth
    },
    
    getCanvasHeight() {
      return uni.getSystemInfoSync().windowWidth // 保持正方形
    },
    
    handleTouchStart(e) {
      this.touchStartX = e.touches[0].clientX
      this.touchStartY = e.touches[0].clientY
    },
    
    handleTouchEnd(e) {
      const endX = e.changedTouches[0].clientX
      const endY = e.changedTouches[0].clientY
      
      const deltaX = endX - this.touchStartX
      const deltaY = endY - this.touchStartY
      
      // 判断滑动方向
      if(Math.abs(deltaX) > Math.abs(deltaY)) {
        // 水平方向
        if(deltaX > 0 && this.direction !== 'left') {
          this.direction = 'right'
        } else if(deltaX < 0 && this.direction !== 'right') {
          this.direction = 'left'
        }
      } else {
        // 垂直方向
        if(deltaY > 0 && this.direction !== 'up') {
          this.direction = 'down'
        } else if(deltaY < 0 && this.direction !== 'down') {
          this.direction = 'up'
        }
      }
    },
    
    handleMouseDown(e) {
      this.isMouseDown = true
      this.mouseStartX = e.touches[0].clientX
      this.mouseStartY = e.touches[0].clientY
    },
    
    handleMouseMove(e) {
      if(this.isMouseDown) {
        const endX = e.touches[0].clientX
        const endY = e.touches[0].clientY
        
        const deltaX = endX - this.mouseStartX
        const deltaY = endY - this.mouseStartY
        
        // 判断滑动方向
        if(Math.abs(deltaX) > Math.abs(deltaY)) {
          // 水平方向
          if(deltaX > 0 && this.direction !== 'left') {
            this.direction = 'right'
          } else if(deltaX < 0 && this.direction !== 'right') {
            this.direction = 'left'
          }
        } else {
          // 垂直方向
          if(deltaY > 0 && this.direction !== 'up') {
            this.direction = 'down'
          } else if(deltaY < 0 && this.direction !== 'down') {
            this.direction = 'up'
          }
        }
      }
    },
    
    handleMouseUp(e) {
      this.isMouseDown = false
    },
    
    async getUserInfo() {
      try {
        const { userInfo } = await uni.getUserProfile({
          desc: '用于显示排行榜头像和昵称'
        })
        this.currentUser = {
          nickname: userInfo.nickName,
          avatar: userInfo.avatarUrl
        }
      } catch(e) {
        console.log('获取用户信息失败:', e)
      }
    },
    
    loadRankList() {
      try {
        const rankData = uni.getStorageSync(RANK_STORAGE_KEY)
        if(rankData) {
          this.rankList = JSON.parse(rankData)
        }
      } catch(e) {
        console.error('读取排行榜失败:', e)
      }
    },
    
    saveRankList() {
      try {
        uni.setStorageSync(RANK_STORAGE_KEY, JSON.stringify(this.rankList))
      } catch(e) {
        console.error('保存排行榜失败:', e)
      }
    },
    
    updateRankList(score) {
      const newRecord = {
        score,
        nickname: this.currentUser.nickname || '匿名用户',
        avatar: this.currentUser.avatar,
        date: new Date().toLocaleDateString(),
        isCurrentUser: true
      }
      
      // 移除旧的"当前用户"标记
      this.rankList.forEach(item => {
        item.isCurrentUser = false
      })
      
      // 插入新记录并排序
      this.rankList.push(newRecord)
      this.rankList.sort((a, b) => b.score - a.score)
      
      // 限制排行榜长度
      if(this.rankList.length > MAX_RANK_COUNT) {
        this.rankList = this.rankList.slice(0, MAX_RANK_COUNT)
      }
      
      this.saveRankList()
    }
  }
}
</script>

<style lang="less">
@import '../../styles/uni.less';

.snake-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: @spacing-md;
  min-height: 100vh;
  background-color: @bg-color;
  
  .game-container {
    position: relative;
    margin: @spacing-xl 0;
    
    .game-canvas {
      background-color: @bg-color-grey;
      box-shadow: 0 2px 12px rgba(0,0,0,0.1);
      border-radius: @border-radius-md;
    }
    
    .keyboard-tips {
      text-align: center;
      margin-top: @spacing-md;
      color: @text-color-light;
      font-size: @font-size-sm;
    }
  }
  
  .control-panel {
    width: 100%;
    max-width: 600px;
    
    .game-info {
      display: flex;
      justify-content: space-between;
      margin-bottom: @spacing-lg;
      padding: 0 @spacing-lg;
      
      .score, .high-score {
        font-size: @font-size-lg;
        color: @text-color;
        font-weight: bold;
      }
    }
    
    .buttons {
      display: flex;
      justify-content: center;
      gap: @spacing-lg;
      margin-bottom: @spacing-xl;
      
      .control-btn {
        background-color: @primary-color;
        color: #fff;
        padding: @spacing-sm @spacing-xl;
        border-radius: @border-radius-md;
        font-size: @font-size-md;
        
        &:active {
          opacity: 0.8;
        }
      }
    }
    
    .direction-keys {
      .key-row {
        display: flex;
        justify-content: center;
        gap: @spacing-sm;
        margin-bottom: @spacing-sm;
        
        .key-btn {
          width: 80rpx;
          height: 80rpx;
          line-height: 80rpx;
          text-align: center;
          background-color: @bg-color-grey;
          border-radius: @border-radius-sm;
          font-size: @font-size-xl;
          color: @text-color;
          
          &:active {
            background-color: @bg-color-hover;
          }
        }
      }
    }
  }
  
  .rank-section {
    width: 100%;
    max-width: 600px;
    margin-top: @spacing-xl;
    margin-bottom: @spacing-xl;
  }
}
</style> 